
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "cmsis_os2.h"
#include "ohos_init.h"
#include "do_ctrl_task.h"
#include "softbus_tool/transmission.h"
#include "msg_adapter/msg_adapter.h"
#include "iot_dido.h"
#include "cJSON.h"
#include "utils_log.h"

//DO控制投影仪电动吊架、幕布升降的任务(COM1、COM3做投影仪吊架控制,COM5、COM6做幕布控制)

static osThreadId_t g_tid = NULL;
#define  DO_CTRL_TASK_PRIO  17              //任务优先级
#define  DO_CTRL_TASK_STACK_SIZE  0x1000    //任务栈大小
#define MAX_CTRL_MSG_LEN  1024

static osTimerId_t *g_timerId = NULL;

enum CTRL_MODE
{
    CTRL_MODE_UNKOWN = 0,
    CTRL_MODE_UP = 1,
    CTRL_MODE_DOWN = 2,
    CTRL_MODE_STOPPED = 3
};

#define ONE_MIN_TIME         60*1000

//定时一分钟，复位DO输出
static void  TimerCallback(void *arg) 
{
    printf("enter timer callback...\r\n");
    setDigiOutput(PIN_NO_1, 0);
    setDigiOutput(PIN_NO_3, 0);
    setDigiOutput(PIN_NO_5, 0);
    setDigiOutput(PIN_NO_6, 0);
}

int CreateTimer()
{
    if (NULL != g_timerId) { return 0; }
    
    g_timerId = osTimerNew((osTimerFunc_t)TimerCallback, osTimerOnce, NULL, NULL);
    if (NULL == g_timerId){
        printf("new os timer failed\r\n");
        LOG_TO_FILE("new os timer failed");
        return -1;   
    }
    
    return 0;
}

void DestoryTimer()
{
    if (NULL == g_timerId) { return; }

    osTimerDelete(g_timerId);
    g_timerId = NULL;
}

int ParseDoCtrlMsg(const char *jsonData, uint8_t *hangerMode, uint8_t *screenMode, int *screenTime)
{
    if(NULL==jsonData || NULL==hangerMode || NULL==screenMode || NULL==screenTime) {
       printf("input params is invalid");
       return -1;
    }

    int ret = 0;
    cJSON *root = cJSON_Parse(jsonData);
    if (NULL == root) {
        ret = -1;
        printf("parse  DO ctrl msg failed");
        goto JSON_FAILED;
    }

    cJSON *objHanger = cJSON_GetObjectItem(root, "HangerMode");       
    if (NULL != objHanger){
        *hangerMode = objHanger->valueint;
    } else {
        *hangerMode = CTRL_MODE_UNKOWN;
    }

    cJSON *objScreen = cJSON_GetObjectItem(root, "ScreenMode");       
    if (NULL != objScreen){
        *screenMode = objScreen->valueint;
    } else {
        *screenMode = CTRL_MODE_UNKOWN;
    }

    cJSON *objScreenTime = cJSON_GetObjectItem(root, "ScreenTime");       
    if (NULL != objScreenTime){
        *screenTime =  objScreenTime->valueint;
    }

JSON_FAILED: 
    if(root){
        cJSON_Delete(root);
        root = NULL;
    }

    return ret;
}

//控制投影仪电动吊架
void CtrlElectricHangerStatus(uint8_t hangerMode)
{
    switch (hangerMode)
    {
        case CTRL_MODE_UP://先控制暂停再控制上升
            setDigiOutput(PIN_NO_1,0);
            setDigiOutput(PIN_NO_3,0);
            usleep(1000*100);
            setDigiOutput(PIN_NO_1,0);
            setDigiOutput(PIN_NO_3,1);
        break;

        case CTRL_MODE_DOWN://先控制暂停再控制下降
            setDigiOutput(PIN_NO_1,0);
            setDigiOutput(PIN_NO_3,0);
            usleep(1000*100);
            setDigiOutput(PIN_NO_1,1);
            setDigiOutput(PIN_NO_3,0);
        break;

        case CTRL_MODE_STOPPED:
            setDigiOutput(PIN_NO_1,0);
            setDigiOutput(PIN_NO_3,0);
        break;

        case CTRL_MODE_UNKOWN:
        default:
        break;
    }
}

//控制幕布
void CtrlScreenStatus(uint8_t screenMode, int screenTime)
{
    switch(screenMode)
    {
        case CTRL_MODE_UP:
            setDigiOutput(PIN_NO_5,1);
            setDigiOutput(PIN_NO_6,0);
        break;

        case CTRL_MODE_DOWN:
            setDigiOutput(PIN_NO_5,0);
            setDigiOutput(PIN_NO_6,1);
        break;

        case CTRL_MODE_STOPPED:
            setDigiOutput(PIN_NO_5, 0);
            setDigiOutput(PIN_NO_6, 0);
        break;

        case CTRL_MODE_UNKOWN:
        default:
        break;
    }
}

void DoCtrlTask(void *arg)
{
    DigiInit();
    InitMsgQueue();
    int num = 0;
    while (num == 0)
    {
        GetAllOnlineNum(&num);
        sleep(1);
    }
    
    BirefCreateSessionServer();

    int ret = 0;
    char ctrlMsg[MAX_CTRL_MSG_LEN] =  {0};
    uint8_t hangerMode=CTRL_MODE_UNKOWN, screenMode=CTRL_MODE_UNKOWN;
    int screenTime = 0;
    while(1)
    {
        ret = RecvMsg(ctrlMsg, MAX_CTRL_MSG_LEN);
        if (ret == -1) {
            printf("[%s-%d]:receive message failed\r\n",__func__,__LINE__);
            sleep(1);
            continue;
        }
       
        ret = ParseDoCtrlMsg(ctrlMsg, &hangerMode, &screenMode, &screenTime);
        if (ret != 0){
            sleep(1);
            continue;
        }
        printf("hangerMode:%d, screenMode:%d, screenTime:%d\n", hangerMode,screenMode, screenTime);

        CtrlElectricHangerStatus(hangerMode);
        CtrlScreenStatus(screenMode, screenTime);
        hangerMode = screenMode = CTRL_MODE_UNKOWN;  //重新复位控制模式,定时一分钟复位
        CreateTimer();
        osTimerStart(g_timerId, ONE_MIN_TIME);
        sleep(1);
    }
}

int StartDoCtrlTask(void *arg)
{
    osThreadAttr_t attr;
    attr.name = "DO_CtrlTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = DO_CTRL_TASK_STACK_SIZE;
    attr.priority = DO_CTRL_TASK_PRIO;
    g_tid = osThreadNew((osThreadFunc_t)DoCtrlTask, arg, &attr);
    if (g_tid == NULL) {
        printf("Failed to create thread!\n");
        LOG_TO_FILE("Failed to create thread!");
        return -1;
    }

    return 0;
}

void StopDoCtrlTask()
{
    if (NULL == g_tid) {
        return;
    }

    osThreadTerminate(g_tid);
    g_tid = NULL;
}